package cn.tedu.dictionary.service.imp;

import cn.hutool.bloomfilter.BloomFilter;
import cn.tedu.dictionary.mapper.SysDictTypeMapper;
import cn.tedu.dictionary.pojo.entity.SysDictType;
import cn.tedu.dictionary.service.SysDictTypeService;
import org.redisson.api.RKeys;
import org.redisson.api.RLock;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Transactional(readOnly = false,
        rollbackFor = Exception.class,
        isolation = Isolation.READ_COMMITTED,
        propagation = Propagation.REQUIRED)
@Service
public class SysDictTypeServiceImpl implements SysDictTypeService {

    @Autowired
    private SysDictTypeMapper sysDictTypeMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private BloomFilter bloomFilter;

    @Transactional(readOnly = true)
    @Override
    public SysDictType selectById(Long dictId) {
        String key="dict:"+dictId;
        //if(!bloomFilter.contains(key))return null;//或者抛出异常
        //从Caffeine本次缓存取数据
        Cache typeCache = cacheManager.getCache("dictTypeCache");
        SysDictType dictType = typeCache.get(key,SysDictType.class);
        if(dictType!=null)return dictType;
        //从redis缓存取数据,缓存中有则直接返回
        ValueOperations vo = redisTemplate.opsForValue();
        dictType=(SysDictType) vo.get("dict:"+dictId);
        if(dictType!=null){
            typeCache.put(key,dictType);
            return dictType;
        }
        //缓存中没有则去查询数据库，并将查到的数据放到缓存中
        dictType=sysDictTypeMapper.selectById(dictId);
        typeCache.put(key,dictType);
        vo.set("dict:"+dictId,dictType);
        return dictType;
    }

    @Override
    public int saveSysDictType(SysDictType dictType) {
           ValueOperations vo = redisTemplate.opsForValue();
           //基于redis客户端直接保证其幂等性
           boolean isRequested=vo.setIfAbsent("dict:"+dictType.getDictType(),dictType,30, TimeUnit.MINUTES);
           if(!isRequested) throw new RuntimeException("请不要重复提交");
            // 处理业务逻辑
           dictType.setCreateTime(new Date());
           dictType.setUpdateTime(new Date());
           //写关系型数据库
           int rows = sysDictTypeMapper.insert(dictType);
           //写内存数据库
           vo.set("dict:" + dictType.getDictId(), dictType);
           //将上面的代码也可以交给canal
           return rows;
      }
}
